package com.example.behaviorpattern.interpreter;

interface Expression {
    int interpret(Context context);
}

class Context {
    // 可以添加一些全局信息或者方法，这里简化处理
}

class NumberExpression implements Expression {
    private int number;
    
    public NumberExpression(int number) {
        this.number = number;
    }
    
    @Override
    public int interpret(Context context) {
        return number;
    }
}

class AddExpression implements Expression {
    private Expression firstExpression, secondExpression;
    
    public AddExpression(Expression firstExpression, Expression secondExpression) {
        this.firstExpression = firstExpression;
        this.secondExpression = secondExpression;
    }
    
    @Override
    public int interpret(Context context) {
        return firstExpression.interpret(context) + secondExpression.interpret(context);
    }
}

class SubtractExpression implements Expression {
    private Expression firstExpression, secondExpression;
    
    public SubtractExpression(Expression firstExpression, Expression secondExpression) {
        this.firstExpression = firstExpression;
        this.secondExpression = secondExpression;
    }
    
    @Override
    public int interpret(Context context) {
        return firstExpression.interpret(context) - secondExpression.interpret(context);
    }
}

/**
 * 解释器模式是一种设计模式，用于为某个语言定义其语法表示，并提供一个解释器来解决这个语言中的句子。这种模式被用于那些频繁变化或复杂的处理逻辑领域中，主要用于开发专门的脚本语言、规则引擎等场合。
 * 使用场景：
 * 当有一个语言需要解释执行，并且可以将该语言中的句子表示为一个抽象语法树时。
 * 当某个特定类型问题发生的频率足够高时，可以将问题的各个实例表述为一个简单语言的句子，这样就可以构建一个解释器，通过解释这些句子来解决问题。
 * 常用组件：
 * AbstractExpression（抽象表达式）：声明一个抽象的解释操作，这个接口为抽象语法树中所有的节点共享。
 * TerminalExpression（终结符表达式）：实现与文法中的终结符相关联的解释操作。实例表示句子中的终端符。
 * NonTerminalExpression（非终结符表达式）：为文法中的非终结符实现解释操作。对规则AbstractExpression ::= NonTerminalExpression | TerminalExpression中的NonTerminalExpression部分。
 * Context（上下文）：包含解释器之外的一些全局信息。
 * Client（客户端）：构建（或被给定）该文法中的句子的抽象语法树，调用解释操作。
 */
public class InterpreterPatternDemo {
    public static void main(String[] args) {
        Context context = new Context();
        Expression expression = new AddExpression(new NumberExpression(5), new SubtractExpression(new NumberExpression(10), new NumberExpression(4)));
        System.out.println(expression.interpret(context));
    }
}